import 'dart:async';

import 'package:flutter/material.dart';
import 'package:quiver/async.dart';
import 'package:quiver/time.dart';

/// kiven 2021/8/26
class QuiverAsyncDemo extends StatelessWidget {
  StreamSubscription? streamSubscription;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text('QuiverAsyncDemo'),
          centerTitle: true,
        ),
        body: SingleChildScrollView(
          child: Wrap(
            spacing: 8,
            runSpacing: 4,
            children: [
              addTitle('Classes'),
              addAction('CountdownTimer', () {
                streamSubscription?.cancel();
                print('- CountdownTimer');
                final cdt = CountdownTimer(
                  Duration(seconds: 9),
                  aSecond,
                );
                streamSubscription = cdt.listen((event) {
                  print(event.elapsed);
                });
              }),
              addAction('FutureStream', () {
                streamSubscription?.cancel();
                print('- FutureStream');
                final cdt = FutureStream(_getCountdownTimer());
                streamSubscription = cdt.listen((event) {
                  print(event.elapsed);
                });
              }),
              addAction('Metronome', () {
                streamSubscription?.cancel();
                print('- Metronome');
                // 不加.take(9)的话会一直循环输出。take(9)循环九次输出。
                // final cdt = Metronome.epoch(aSecond).take(9);
                final cdt = Metronome.periodic(aSecond).take(9);
                streamSubscription = cdt.listen(print);
              }),
              addAction('StreamBuffer', () {
                streamSubscription?.cancel();
                print('- StreamBuffer');
                final cdt = StreamBuffer<int>();
                cdt.addStream(Metronome.periodic(aSecond)
                    .take(9)
                    .map((event) => event.toString().codeUnits));
                cdt.read(100).then(
                    (value) => print(String.fromCharCodes(value.toList())));
              }),
              addAction('StreamRouter', () {
                streamSubscription?.cancel();
                print('- StreamRouter');
                final cdt = StreamRouter(Metronome.periodic(aSecond).take(9));
                cdt
                    .route((event) => event.microsecond % 2 == 0)
                    .listen((event) {
                  print('route1:$event');
                });

                cdt
                    .route((event) => event.microsecond % 2 == 1)
                    .listen((event) {
                  print('route2:$event');
                });
              }),
              addTitle('Functions'),
              addAction('byteStreamToString', () {
                print('- byteStreamToString');
                final cdt = byteStreamToString(Metronome.periodic(aSecond)
                    .take(4)
                    .map((event) => event.toString().codeUnits));
                cdt.then(print);
              }),
              addAction('collect', () {
                print('- collect');
                // collect 按顺序执行Future
                final cdt = collect([
                  Future.delayed(aSecond * 2, () => 'Hello girls!'),
                  Future.delayed(aSecond * 5, () => 'I\'m Kiven')
                ]);
                cdt.listen(print);
              }),
              addAction('concat', () {
                print('- concat');
                // concat 按顺序执行Stream
                final cdt = concat([
                  Metronome.periodic(aSecond)
                      .take(2)
                      .map((event) => 'stream1 $event'),
                  Metronome.periodic(aSecond)
                      .take(3)
                      .map((event) => 'stream2 $event')
                ]);
                cdt.listen(print);
              }),
              addAction('enumerate', () {
                print('- enumerate');
                // enumerate 将Stream的结果加上序号
                final cdt = enumerate(Metronome.periodic(aSecond).take(3));
                cdt.listen(print);
              }),
            ],
          ),
        ));
  }

  Future<CountdownTimer> _getCountdownTimer() async {
    return CountdownTimer(
      Duration(seconds: 9),
      aSecond,
    );
  }

  addTitle(String title) {
    return Center(
      child: Text(title),
    );
  }

  addAction(String title, Function() action) {
    return ElevatedButton(
      onPressed: action,
      child: Text(title),
    );
  }
}
